/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.babeuf.form.fields 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.FocusEvent;
	import net.babeuf.form.errors.FieldError;
	import net.babeuf.form.event.FieldErrorEvent;
	import net.babeuf.form.event.FieldEvent;
	import net.babeuf.form.messages.Messages;
	import net.babeuf.form.sensors.AbstractSensor;
	/**
	 * ...
	 * @author damien pegoraro
	 */
	public class AbstractField extends EventDispatcher implements IField
	{
		/**
		* Dispatched when en error is handled for the current field
		* @eventType net.babeuf.form.event.FieldErrorEvent.FIELD_ERROR
		*/
		[Event(name="fieldError", type="net.babeuf.form.event.FieldErrorEvent")]

		/**
		* Dispatched when current field value is updated
		* @eventType net.babeuf.form.event.FieldEvent.FIELD_CHANGED
		*/
		[Event(name="fieldChanged", type = "net.babeuf.form.event.FieldEvent")]
		
		/**
		* Dispatched when focus is given to the current field
		* @eventType net.babeuf.form.event.FieldEvent.FOCUS_IN
		*/
		[Event(name="focusIn", type = "net.babeuf.form.event.FieldEvent")]
		
		/**
		* Dispatched when focus is released from the current field
		* @eventType net.babeuf.form.event.FieldEvent.FOCUS_OUT
		*/
		[Event(name="focusOut", type="net.babeuf.form.event.FieldEvent")]
		
		
		public var name : String = "" ; 	
		
		public var optional : Boolean = false ; 
		public var notSent  : Boolean = false ; 
		public var validateOnFocusOut : Boolean = false ; 
		
		protected var _sensors : Array ;
		protected var _error : String = "" ; 
		
		protected var _minError : String = Messages.GENERIC_MIN  ; 
		protected var _maxError : String = Messages.GENERIC_MAX  ; 
		protected var _emptyError : String = Messages.GENERIC_EMPTY  ; 
		protected var _invalidError : String = Messages.GENERIC_INVALID ; 
		
		public function AbstractField( ) 
		{
			_sensors = new Array() ; 
			empty() ; 
		}
		
		public function dispose() : void
		{
			for each ( var sensor : AbstractSensor in _sensors ) 
			{
				if ( sensor ) sensor.dispose() ; 
			}
			_sensors = null ; 
		}
		
		public function setTabIndex( index : int) : int
		{
			return index+1 ;
		}
		
		public function giveFocus() : void
		{
			
		}
			
		public function addSensor( sensor : AbstractSensor ) : void
		{
			_sensors.push( sensor ) ; 
		}
				
		
		public function empty() : void
		{
			_error = "" ; 
			_updateSensors( true )   ;
		}
		
		public function getValue() : * 
		{
			return null ; 
		}
		
		public function setValue( value : * ) : void
		{
			
		}
			
		public function validate() : Boolean
		{
			_updateSensors(true) ; 
			_error = "" ; 
			return true ;
		}
		
		public function autoValidate() : Boolean
		{
			var _opt : Boolean = optional ; 
			optional = true ; 
			var out : Boolean =  validate() ; 
			optional = _opt ; 
			return out ;
		}
		
		public function getErrorCode() : FieldError
		{
			return new FieldError(this,_error) ; 
		}
		
		public function setMinSizeError( code : String ) : void
		{
			_minError = code ; 
		}
		
		public function setMaxSizeError( code : String ) : void
		{
			_maxError = code ; 
		}
		
		public function setEmptyError( code : String ) : void
		{
			_emptyError = code ; 
		}
		
		public function setInvalidError( code : String ) : void
		{
			_invalidError = code ; 
		}
		
		public function setErrors( minCode : String = "", maxCode : String = "", emptyCode : String = "", invalidCode : String = "" ) : void
		{
			_minError = minCode && minCode.length > 0 ? minCode : Messages.GENERIC_MIN ; 
			_maxError = maxCode && maxCode.length > 0 ? maxCode : Messages.GENERIC_MAX ; 
			_emptyError = emptyCode && emptyCode.length > 0 ? emptyCode : Messages.GENERIC_EMPTY ; 		
			_invalidError = invalidCode && invalidCode.length > 0 ? invalidCode : Messages.GENERIC_INVALID ; 		
		}
		
		public function setCommonErrors( emptyCode : String = "", invalidCode : String = "" ) : void
		{
			_emptyError = emptyCode && emptyCode.length > 0 ? emptyCode : Messages.GENERIC_EMPTY ; 		
			_invalidError = invalidCode && invalidCode.length > 0 ? invalidCode : Messages.GENERIC_INVALID ; 		
		}
		
		protected function _throwError() : void
		{
			dispatchEvent( new FieldErrorEvent( FieldErrorEvent.FIELD_ERROR, this, _error ) ) ; 
		}
		
		protected function _throwFocusIn( e:  FocusEvent = null ) : void
		{
			dispatchEvent( new FieldEvent( FieldEvent.FOCUS_IN, this) ) ; 
		}
		
		protected function _throwFocusOut( e:  FocusEvent = null ) : void
		{
			dispatchEvent( new FieldEvent( FieldEvent.FOCUS_OUT, this) ) ; 
		}
		
		protected function _notifyChanged( e:  Event = null ) : void
		{
			dispatchEvent( new FieldEvent( FieldEvent.FIELD_CHANGED, this )) ; 
		}
		
		
		protected function _updateSensors( ok : Boolean  = true ) : void
		{
			for each ( var s:  AbstractSensor in _sensors ) 
			{
				if ( ok ) s.ok( ) ;
				else s.ko() ; 
			}
			if ( !ok ) _throwError() ; 
		}
		
	}

}